/*
 Copyright 2009 Abdulla Abdurakhmanov (abdulla@latestbit.com)
 Original sources are available at www.latestbit.com

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.

 ServerSkeleton.hpp. Created on: 28.10.2009 15:32:47 
 */

#ifndef SERVERSKELETON_HPP_
#define SERVERSKELETON_HPP_

#include "smartobjects/SmartObjectsDefs.hpp"
#include "smartobjects/IServerSkeleton.hpp"
#include "smartobjects/core/SmartObject.hpp"
#include "smartobjects/core/ICommandProcessor.hpp"
#include "smartobjects/IRemoteSmartObject.hpp"
#include "smartobjects/network/INetworkCommand.hpp"
#include "smartobjects/network/ConnectionHandler.hpp"
#include "smartobjects/coders/CallInterfaceOperationRequest.hpp"
#include "smartobjects/coders/CallInterfaceOperationResponse.hpp"

namespace smartobjects {

class ServerSkeleton : public virtual SmartObject, public virtual IServerSkeleton, public ICommandProcessorHandler {
public:
	SO_DLLPRFX ServerSkeleton();
	SO_DLLPRFX virtual ~ServerSkeleton();

	SO_DLLPRFX virtual void publish( ISmartBus* poBus, IEndpointLocation* poLocation) ;
	SO_DLLPRFX virtual void publish( ISmartObject* poBaseObject );
	SO_DLLPRFX virtual void publish( ISmartObject* poBaseObject, ConnectionHandler* poConnectionHandler );
	SO_DLLPRFX virtual void unpublish();

	SO_DLLPRFX virtual void registerInstance ( ConnectionHandler* poConnectionHandler ) ;
	SO_DLLPRFX virtual void unregisterInstance () ;

	SO_DLLPRFX virtual LifecycleControlParams& getLifecycleControlParams() ;

	SO_DLLPRFX virtual bool isPublished() const;
	SO_DLLPRFX virtual IEndpointLocation* getPublishedLocation() ;

	SO_DLLPRFX virtual void setThreadModel(ThreadModel nModel) ;
	SO_DLLPRFX virtual ThreadModel getThreadModel() ;
	SO_DLLPRFX virtual size_t getRequestQueueSize() const;

	SO_DLLPRFX static RequestContext* getCurrentRequestContext();

protected:
	#include "ServerSkeletonRequestQueueItem.inl"

protected:
	// from ICommandProcessorHandler
	SO_DLLPRFX virtual void onResponseReceived(
			ConnectionHandler* poHandler,
			INetworkCommand* poRequest,
			INetworkCommand* poResponse,
			RefObject* poUserObject
	);

	SO_DLLPRFX virtual void onResponseTimeout(
			INetworkCommand* poRequest,
			RefObject* poUserObject
	);

	SO_DLLPRFX virtual void onRequestReceived(
			ConnectionHandler* poHandler,
			INetworkCommand* poRequest
	);

	SO_DLLPRFX virtual bool isCommandIdSupported(
			ConnectionHandler* poHandler,
			INetworkCommand* poRequest
	);

protected:
	SO_DLLPRFX virtual void sendResponse(ConnectionHandler* poConnectionHandler, CallInterfaceOperationResponse* poResponse);
	SO_DLLPRFX virtual void sendSystemExceptionResponse(ConnectionHandler* poConnectionHandler, CallInterfaceOperationRequest* poRequest, const std::exception& ex);
	SO_DLLPRFX virtual ICommandProcessor* getCurrentCommandProcessor();

	// The method must be implemented in the generated classes
	SO_DLLPRFX virtual void onCallRequestReceived(ConnectionHandler* poConnectionHandler, CallInterfaceOperationRequest* poRequest) = 0;

protected:
	SO_DLLPRFX virtual void onDequeRequest();
	SO_DLLPRFX virtual void releaseCurrentNetworkEnv();

protected:
	typedef std::list<RequestQueueItem> RequestQueue;
	typedef boost::unordered_map< ConnectionHandler*, RequestQueue > RequestQueuePerClient;

	boost::recursive_mutex m_mxSkeleton;
	RequestQueue m_aRequestQueue;
	RequestQueuePerClient m_mRequestQueuePerClient;
	unsigned int m_nRequestQueuePerClientIdx;
	ThreadPool* m_poThreadPool;
	ThreadPool::TaskId m_nTaskId;
	boost::shared_mutex m_mxRequestQueueProcessor;
	mutable boost::recursive_mutex m_mxRequestQueue;
	IServerSkeleton::ThreadModel m_nThreadModel;
	LifecycleControlParams m_oLifecycleControlParams;
	IEndpointLocation* m_poEndpointLocation;
	bool m_bRegistered, m_bPublished, m_bDefferedUnpublish;
	boost::thread_specific_ptr<bool> m_poTlsCallProcessingStatus;

	static boost::thread_specific_ptr<RefObject> m_poTlsCurrentRequestContext;

	ConnectionHandler* m_poAvailForConnectionHandler;

};

}

#endif /* SERVERSKELETON_HPP_ */
